#define SEXT(x) ((int)(x))
#define ZEXT(x) ((unsigned int)(x))
#define U(x) ((unsigned int)(x))
#define S(x) ((int)(x))
#define OPCODE ((IR & 0x7FU)) // CHECKED
#define RS1    (ZEXT(IR & 0xF8000U) >> 15) // CHECKED
#define RS2    (ZEXT(IR & 0x1F00000U) >> 20) // CHECKED
#define SHAMT RS2
#define UIMM RS1
#define RD     (ZEXT(IR & 0xF80U) >> 7) // CHECKED
#define FUNCT7 (ZEXT(IR & 0xFE000000U) >> 25) // CHECKED
#define FUNCT5 RS2 // for rv32f/d
#define FUNCT3 (ZEXT(IR & 0x7000U) >> 12) // CHECKED
#define IMM_I  (SEXT(IR & 0xFFF00000U) >> 20) //CHECKED
#define IMM_I_ZEXT  (ZEXT(IR & 0xFFF00000U) >> 20) //CHECKED
#define IMM_S  (SEXT((IR & 0xFE000000U)|((IR&0xF80U)<<13))>>20) // CHECKED
#define IMM_B  (SEXT((ZEXT(IR & 0x7E000000U)>>1)|((IR & 0x80U)<<23)|((IR & 0xF00U)<<12)|(IR & 0x80000000U)) >> 19) // CHECKED
#define IMM_U  (SEXT(IR & 0xFFFFF000U) >> 12) // CHECKED
#define IMM_J  ((ZEXT(IR & 0x7FE00000U) >> 20)|(ZEXT(IR&0x100000U)>>9)|(IR&0xFF000U)|(SEXT(IR&0x80000000U)>>11)) // CHECKED
#define RS3    (ZEXT(IR & 0xE0000000U) >> 27)
#define R4_FMT (ZEXT(IR & 0x6000000U) >> 25)
#define R4_RM  (ZEXT(IR & 0x7000U) >> 12)
#define SEXT8(x) (SEXT(ZEXT(x) << 24)>>24)
#define SEXT16(x) (SEXT(ZEXT(x) << 16)>>16)
#define ZEXT8(x) (ZEXT(ZEXT(x) << 24)>>24)
#define ZEXT16(x) (ZEXT(ZEXT(x) << 16)>>16)

// #define PARAM_ASYNC_CSRRW // 使用异步csr读写

#define MIE_MASK 0x4
#define MPIE_MASK 0x80
#define MPP_MASK 0x1800
#define MIE_SHFT 0x2
#define MPIE_SHFT 0x7
#define MPP_SHFT 0xB
#define set_mstatus_mpie(mstatus,mpie) (mstatus = ((mstatus&~MPIE_MASK)|((mpie&0x1)<<MPIE_SHFT)))
#define set_mstatus_mie(mstatus,mie) (mstatus = ((mstatus&~MIE_MASK)|((mie&0x1)<<MIE_SHFT)))
#define set_mstatus_mpp(mstatus,mpp) (mstatus = ((mstatus&~MPP_MASK)|((mpp&0x3)<<MPP_SHFT)))
#define clr_mstatus_mie(mstatus) (mstatus &= ~(1<<MIE_SHFT))
#define mstatus_mpie(mstatus) ((mstatus&MPIE_MASK)>>MPIE_SHFT)
#define mstatus_mie(mstatus) ((mstatus&MIE_MASK)>>MIE_SHFT)
#define mstatus_mpp(mstatus) ((mstatus&MPP_MASK)>>MPP_SHFT)

#define CSR_MSTATUS 0x300
#define CSR_MIE 0x304
#define CSR_MTVEC 0x305
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344
#define CSR_MATP 0xBC0
#define CSR_HALT 0xC00
#define CSR_MTIME 0xF15
#define CSR_MTIMECMP 0xF16
#define CSR_TESTNUM 0xF20
#define CSR_TESTSTR 0xF21

// 22
#define DEF_R_INST(name,funct7,funct3,opcode,op){   \
    if (OPCODE == (opcode) && FUNCT3 == (funct3) && FUNCT7 == (funct7)) { \
        if (PARAM_DEBUG){printf ("%s x%u,x%u,x%u\n", #name, RD, RS1, RS2); fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}
#define DEF_I_INST(name,funct3,opcode,op){  \
    if (OPCODE == (opcode) && FUNCT3 == (funct3) ) {\
        if (PARAM_DEBUG){printf ("%s x%u,%d(x%u)\n", #name, RD, IMM_I, RS1);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}
#define DEF_S_INST(name,funct3,opcode,op){\
    if (OPCODE == (opcode) && FUNCT3 == (funct3)) {\
        if (PARAM_DEBUG){printf ("%s x%u,%d(x%u)\n", #name, RS2, IMM_S, RS1);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}
#define DEF_B_INST(name,funct3,opcode,op){\
    if (OPCODE == (opcode) && FUNCT3 == (funct3)) {\
        if (PARAM_DEBUG){printf ("%s x%u,x%u,%d\n", #name, RS1, RS2, IMM_B);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}
#define DEF_U_INST(name,opcode,op){\
    if (OPCODE == (opcode)) {\
        if (PARAM_DEBUG){printf ("%s x%u,%d\n", #name, RD, IMM_U);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}
#define DEF_J_INST(name,opcode,op){\
    if (OPCODE == (opcode)) {\
        if (PARAM_DEBUG){printf ("%s x%u,%u | IR:%u\n", #name, RD, IMM_J,IR);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}

#define DEF_I_SP_INST(name,funct7,funct3,opcode,op) {\
    if (OPCODE == (opcode) && FUNCT3 == (funct3) && FUNCT7 == (funct7)) { \
        if (PARAM_DEBUG){printf ("%s x%u,x%u,%u\n", #name, RD, RS1, RS2);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}\

#define DEF_I_JMP_INST(name,funct3,opcode,op) { \
    if (OPCODE == (opcode) && FUNCT3 == (funct3) ) {\
        if (PARAM_DEBUG){printf ("%s x%u,%d(x%u)\n", #name, RD, IMM_I, RS1);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}

#define DEF_R4_INST(name, fmt, opcode, op) { \
    if (OPCODE == (opcode) && R4_FMT == (fmt)) { \
        if (PARAM_DEBUG){printf ("%s f%u,f%u,f%u,f%u\n", #name, RD, RS1, RS2, RS3);fflush (stdout);}\
        {op}\
        goto executed;\
    } \
}

#define DEF_R_SP_INST(name,funct7,opcode,op){   \
    if (OPCODE == (opcode) && FUNCT7 == (funct7)) { \
        if (PARAM_DEBUG){printf ("%s f%u,f%u,f%u\n", #name, RD, RS1, RS2);fflush (stdout);}\
        {op}\
        goto executed;\
    }\
}

#define DEF_R2_INST(name,funct7, funct5 ,opcode,op){   \
    if (OPCODE == (opcode) && FUNCT7 == (funct7) && FUNCT5 == (funct5)) { \
        if (PARAM_DEBUG){printf ("%s d%u,s%u\n", #name, RD, RS1);fflush (stdout);} \
        {op}\
        goto executed;\
    }\
}

#define DEF_UNIQUE_INST(name, match, op) {\
    if (IR == (match)) { \
        {op}\
        goto executed;\
    }\
}
